﻿package j.sus2maj7.util
{
	import j.sus2maj7.printer.*;
	import j.sus2maj7.context.*;
	import flash.utils.describeType;
	
	public class ObjectPrinter extends AbstractPrinter
	{
		public var MAX_LEVELS:uint = 4;
		private var _usedObjects:Array;
		
		override public function printToXml(o:*, context:IContext=null):XML
		{
			return ObjectToXML(o, 0);
		}
		
		private function ObjectToXML(o:*, level:uint):XML
		{
			if (level > MAX_LEVELS) return null;
			
			var dt:XML = describeType(o);
			//trace(dt);
			var name:String;
			var val:*;
			var className:String = cleanClass(dt.@name);
			//trace(className);
			var xl:XMLList = dt.accessor.(@access == "readwrite") + dt.variable + dt.constant;
			var node2:XML = <{ className } />;
			var node3:XML;
			
			//addObjectToUsed(o);
			for each (var i:XML in xl)
			{
				name = i.@name
				val = o[name];
				
				if ( typeof(val) != 'object' || val == null)
				{
					if (val != undefined)
						node2.@[name] = val;
				}
				else
				{
					//if (!isUsed(val))
					//{
						//create new node and add it and so on
						//node2[name].@_type = cleanClass(i.@type);
						node3 = ObjectToXML(val, level + 1) ;
						if (node3 != null)
							node2[name].firstChild = node3;
					//}
				}
				
			}
			
			//dynamics
			var j:int = 0;
			var node4:XML;
			for (name in o)
			{
				val = o[name];
				
				//
				if (isNaN(Number(name)) && typeof(val) != 'object')
				{
					if (val != undefined)
						node2.@[name] = val;
				}
				else
				{
					node4 = <item id={name} />
					if (typeof(val) == 'object' )
					{
						
						node3 = ObjectToXML(val, level + 1);
						if (node3 != null)
							node4.appendChild( node3);
					}
					else
					{
						if (val != undefined)
							node4.@value = val;
					}
					
					node2.appendChild(node4);//@type = 'Object'id={name}
				}
				
				j++;
			}
			
			return node2;
		}
		
		private function addObjectToUsed(object:Object):void
		{
			_usedObjects[_usedObjects.length] = object;
		}
		private function isUsed(object:Object):Boolean
		{
			for each(var value:* in this._usedObjects)
			{
				if (object === value)
				{
					return true;
				}
			}
			return false;
		}
		private function cleanClass(s:String):String
		{
			var j:int;
			var rs:String = s;
			if ( (j = s.lastIndexOf('::')) > -1)
				rs = s.substr(j + 2 );
			if ( (j = s.lastIndexOf('>')) > -1)
				rs = 'Vector_' + rs.substr(0, rs.length - 1);
			return rs;
		}
	}
	
}